package com.agou.core.ss;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;

import com.agou.core.util.UtFormat;

/**
 * 系统自定义异常
 * <p>
 * 描述:在系统中不允许直接抛出此异常，而必须抛出此异常的子类
 * </p>
 * 
 * @author agou
 * @version 1.0
 */
public abstract class SSException extends java.lang.Exception implements
		java.io.Serializable {
	/**
	 * 
	 */
	private static final long serialVersionUID = -6560659214454375880L;
	// 异常代码
	private int _exCode = -1;
	// 异常类型
	private String _exType;
	// 异常信息
	private String _exMsg = null;
	// 存放详细的补充信息,此属性在缺省方式下不填，需要时通过addDetail(String strDetailMessage)方法补充
	private List<String> _detailList = null;
	// 调用栈, 当截获系统异常而需要转换为SSException时, 用此栈存放原异常的调用情况, 以利于查错
	private StringBuffer _callStack = null;
	// 源异常, 即导致当前异常发生的原始异常
	private SSThrowable _origin = null;

	/**
	 * 异常的构造函数, 用于子类填写相关信息
	 * 
	 */
	protected SSException(String strExType, int nExCode, String sExStr,Object... args) {
		this._exType = strExType;// 异常类型
		this._exCode = nExCode;// 异常代码
		if (args.length > 0) {
			this._exMsg = UtFormat.format(sExStr, args);// LoggerUtils.format(sExStr,
														// args);// 异常信息
		} else {
			this._exMsg = sExStr;// 异常信息
		}
		this._detailList = null;
	}

	/**
	 * 异常的构造函数, 用于子类填写相关信息
	 * 
	 */
	protected SSException(String strExType, int nExCode, String sExStr,
			Throwable e, String... args) {
		this(strExType, nExCode, sExStr);
		this._origin = new SSThrowable(e);
	}

	/**
	 * 为异常补充更加详细的错误信息
	 */
	public final void addDetail(String detailMessage, Object... args) {
		if (_detailList == null) {
			_detailList = new ArrayList<String>();
		}
		if (args.length > 0) {
			_detailList.add(UtFormat.format(detailMessage, args));// LoggerUtils.format(detailMessage,
																	// args)
		} else {
			_detailList.add(detailMessage);
		}

	}

	/**
	 * 存入捕获到异常时的调用栈
	 */
	public final void saveStackTrace(Throwable e) throws IOException {
		if (this._callStack == null) {
			this._callStack = new StringBuffer();
		}
		ByteArrayOutputStream osCallStack = new ByteArrayOutputStream();
		PrintWriter pw = new PrintWriter(osCallStack);
		pw.print(' ');
		e.printStackTrace(pw);
		pw.flush();
		pw.close();
		this._callStack.append(osCallStack.toString());
		osCallStack.close();
		return;
	}

	/**
	 * 是否有捕获到异常时的调用栈
	 */
	public final boolean hasStackTrace() {
		if (this._callStack != null) {
			return true;
		}
		return false;
	}

	/**
	 * 取得错误的完整说明信息
	 */
	public String getMessage() {
		String errorInfo = _exType + ", " + _exCode + ", " + _exMsg + ", "
				+ _detailList;
		return errorInfo;
	}

	/**
	 * 取得异常类型
	 */
	public String getExType() {
		return _exType;
	}

	/**
	 * 取得错误代码
	 */
	public int getExCode() {
		return _exCode;
	}

	/**
	 * 取得错误信息
	 */
	public String getExMessage() {
		return _exMsg;
	}

	/**
	 * 取得错误补充信息
	 */
	public String getDetail() {
		if (_detailList == null) {
			return "";
		}
		String strDetail = null;
		for (int i = 0; i < _detailList.size(); i++) {
			if (strDetail == null) {
				strDetail = (String) _detailList.get(i);
			} else {
				strDetail += "; " + (String) _detailList.get(i);
			}
		}
		return strDetail;
	}

	/**
	 * 将异常或错误中的调用栈以字符串形式倒出
	 */
	public static String getStringFromStream(Throwable e) {

		ByteArrayOutputStream osCallStack = new ByteArrayOutputStream();
		PrintWriter pw = new PrintWriter(osCallStack);
		e.printStackTrace(pw);
		pw.flush();
		pw.close();
		return osCallStack.toString();
	}

	/**
	 * 取导致当前异常发生的原始异常或错误
	 */
	public SSThrowable getOrigin() {
		return _origin;
	}

}
